﻿using SmarterCharger.App.Infrastructure;
using SmarterCharger.App.Infrastructure.Interfaces;
using SmarterCharger.App.Views;
using SmarterCharger.Library.Infrastructure.Interfaces;
using SmarterCharger.Library.Model;
using SmarterCharger.Library.Services.Interfaces;
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Input;

namespace SmarterCharger.App.ViewModel
{
    public class FirstTimeUserViewModel : ViewModelBase
    {
        private const string AllowAccessUnauthorizedMessage = "There seems to be a problem with the username or password you entered.\n\nCan you check them carefully and try again?";
        private const string AllowAccessUnauthorizedTitle = "Allow access";

        private readonly ISmartPlugLoader _smartPlugLoader;
        private readonly INavigationService _navigationService;
        private readonly IMessageBoxService _messageBoxService;
        private readonly ISettingsService _settingsService;

        #region Properties

        private bool _isLoading;
        public bool IsLoading 
        {
            get { return _isLoading; }
            internal set 
            {
                _isLoading = value;
                RaisePropertyChanged("IsLoading");
                CanChargeChanged();
            }
        }

        private bool _isCredentialsValid;
        public bool IsCredentialsValid 
        {
            get { return _isCredentialsValid; }
            private set
            {
                _isCredentialsValid = value;
                RaisePropertyChanged("IsCredentialsValid");
                CanChargeChanged();
            }
        }

        private string _username;
        public string Username 
        {
            get { return _username; }
            set 
            { 
                _username = value;
                RaisePropertyChanged("Username");
                TryToGetSmartPlugs();
            }
        }

        private string _password;
        public string Password 
        {
            get { return _password; }
            set
            {
                _password = value;
                RaisePropertyChanged("Password");
                TryToGetSmartPlugs();
            }
        }

        public ObservableCollection<SmartPlug> SmartPlugs { get; set; }

        private SmartPlug _selectedSmartPlug;
        public SmartPlug SelectedSmartPlug
        {
            get { return _selectedSmartPlug; }
            set
            {
                _selectedSmartPlug = value;
                RaisePropertyChanged("SelectedSmartPlug");
                CanChargeChanged();
            }
        }

        #endregion

        public FirstTimeUserViewModel(ISmartPlugLoader smartPlugLoader, INavigationService navigationService, IMessageBoxService messageBoxService,
            ISettingsService settingsService)
        {
            if (smartPlugLoader == null) throw new ArgumentNullException("smartPlugLoader");
            if (navigationService == null) throw new ArgumentNullException("navigationService");
            if (messageBoxService == null) throw new ArgumentNullException("messageBoxService");
            if (settingsService == null) throw new ArgumentNullException("settingsService");

            _smartPlugLoader = smartPlugLoader;
            _navigationService = navigationService;
            _messageBoxService = messageBoxService;
            _settingsService = settingsService;

            SmartPlugs = new ObservableCollection<SmartPlug>();
            ChargeCommand = new DelegateCommand(Charge, CanCharge);
        }

        public void LoadData()
        {
            if (IsLoaded)
                return;

            SelectedSmartPlug = _settingsService.GetDefaultSmartPlug();
            Username = _settingsService.GetUsername();
            Password = _settingsService.GetPassword();
            
            IsLoaded = true;
        }

        public void SaveData()
        {
            if(IsCredentialsValid)
            {
                _settingsService.UpdateUsername(Username);
                _settingsService.UpdatePassword(Password);
            }

            if (SelectedSmartPlug != null)
                _settingsService.UpdateDefaultSmartPlug(SelectedSmartPlug);
        }

        #region GetSmartPlugs
        private bool CanGetSmartPlugs()
        {
            return (!string.IsNullOrWhiteSpace(Username)
                && !string.IsNullOrWhiteSpace(Password)
                && !IsLoading);
        }

        private async void GetSmartPlugs()
        {
            IsLoading = true;

            var selectedSmartPlug = SelectedSmartPlug;
            SelectedSmartPlug = null;
            SmartPlugs.Clear();

            var result = await _smartPlugLoader.Load(Username, Password);
            IsCredentialsValid = result.IsCredentialsValid;
            
            if(IsCredentialsValid)
                result.SmartPlugs.ToList().ForEach(s => SmartPlugs.Add(s));
            else
                _messageBoxService.Show(AllowAccessUnauthorizedMessage, AllowAccessUnauthorizedTitle);

            if (selectedSmartPlug != null)
                if (SmartPlugs.Any(s => s.EnergyDeviceId == selectedSmartPlug.EnergyDeviceId))
                    SelectedSmartPlug = SmartPlugs.Single(s => s.EnergyDeviceId == selectedSmartPlug.EnergyDeviceId);

            IsLoading = false;
        }

        private void TryToGetSmartPlugs()
        {
            if (CanGetSmartPlugs())
                GetSmartPlugs();
        }

        #endregion

        #region ChargeCommand

        public ICommand ChargeCommand { get; private set; }

        private void Charge(object parameter)
        {
            _settingsService.UpdateIsFirstTimeUser(false);
            _navigationService.Navigate(ViewNames.StartChargingBatteryView);
        }

        private bool CanCharge(object parameter)
        {
            return (!IsLoading
                && IsCredentialsValid
                && SelectedSmartPlug != null);
        }

        private void CanChargeChanged()
        {
            (ChargeCommand as DelegateCommand).RaiseCanExecuteChanged();
        }

        #endregion
    }
}
